package com.mingqijia.gassafety.shared.handler;

import cn.hutool.json.JSONObject;
import com.gap.basic.base.CommonResponse;
import com.gap.basic.exception.BizException;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Objects;
import java.util.Optional;

/**
 * 系统异常统一拦截处理类
 * @author Damon S.
 */
@Slf4j
@RestControllerAdvice
public final class GlobalResponseHandler implements ResponseBodyAdvice<Object> {

    /**
     * @description 请求参数异常
     * @author zm
     * @param e
     * @return com.gap.basic.base.CommonResponse<java.lang.Void>
    */
    @ResponseBody
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public CommonResponse<Void> validationError(HttpMessageNotReadableException e) {
        log.error("请求参数错误:",e);
        return CommonResponse.failure("请求参数错误");
    }

    @ResponseBody
    @ExceptionHandler(BizException.class)
    public CommonResponse<Void> notExpected(BizException e) {
        log.error("业务异常", e);
        return CommonResponse.failure(e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public CommonResponse<Void> notExpected(MissingServletRequestParameterException e) {
        return CommonResponse.failure(e.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(BindException.class)
    public CommonResponse<Void> notExpected(BindException e) {
        FieldError err = Optional.ofNullable(e.getBindingResult().getFieldError())
                .orElse(new FieldError("name", "field", "null default message"));
        return CommonResponse.failure(err.getDefaultMessage());
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResponse<Void> notExpected(MethodArgumentNotValidException e) {
        FieldError err = Optional.ofNullable(e.getBindingResult().getFieldError())
                .orElse(new FieldError("name", "field", "null default message"));
        return CommonResponse.failure(err.getDefaultMessage());
    }

    @ResponseBody
    @ExceptionHandler
    public CommonResponse<Void> notExpected(Throwable t) {
        log.error("系统发生异常", t);
        return CommonResponse.failure("系统发生异常" + t.getMessage());
    }

    @Override
    public boolean supports(MethodParameter parameter, Class clazz) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object r, MethodParameter parameter, MediaType type,
                                  Class<? extends HttpMessageConverter<?>> clazz,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        String requestUrl = request.getURI().getPath();
        if (requestUrl.contains("swagger") || requestUrl.contains("api-docs")) {
            return r;
        }

        JSONObject tokenObject = null;
        try {
            tokenObject = ApplicationUtils.getTokenObject();
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        if (r instanceof CommonResponse) {
            if (Objects.isNull(tokenObject)) {
                return r;
            }
            ResponseWrapper wrapper = ResponseWrapper.wrap(r);
            wrapper.setToken(tokenObject.getStr("token"));
            return wrapper;
        }
        if (requestUrl.contains(Constants.PATH_ROOT_BUSINESS) ||
                requestUrl.contains(Constants.PATH_ROOT_CONSOLE)) {
            if (Objects.isNull(tokenObject)) {
                return CommonResponse.success(r);
            }
            ResponseWrapper wrapper = ResponseWrapper.wrap(CommonResponse.success(r));
            wrapper.setToken(tokenObject.getStr("token"));
            return wrapper;
        }
        return r;
    }


}